// models/SysRole.js
const mongoose = require("mongoose");
const { Schema } = mongoose;

/**
 * 系统角色表 - 对应 MySQL sys_role 表
 */
const sysRoleSchema = new Schema(
  {
    // 角色ID - 对应MySQL的role_id
    roleId: {
      type: Number,
      required: true,
      unique: true,
      index: true,
      comment: "角色ID",
    },

    // 角色名称 - 对应MySQL的role_name
    roleName: {
      type: String,
      required: [true, "角色名称不能为空"],
      trim: true,
      minlength: [1, "角色名称至少1个字符"],
      maxlength: [30, "角色名称不能超过30个字符"],
      index: true,
      comment: "角色名称",
    },

    // 角色权限字符串 - 对应MySQL的role_key
    roleKey: {
      type: String,
      required: [true, "角色权限字符串不能为空"],
      trim: true,
      uppercase: true,
      minlength: [1, "角色权限字符串至少1个字符"],
      maxlength: [100, "角色权限字符串不能超过100个字符"],
      match: [/^[A-Z_]+$/, "角色权限字符串只能包含大写字母和下划线"],
      index: true,
      comment: "角色权限字符串",
    },

    // 显示顺序 - 对应MySQL的role_sort
    roleSort: {
      type: Number,
      required: [true, "显示顺序不能为空"],
      min: [0, "显示顺序不能小于0"],
      max: [9999, "显示顺序不能超过9999"],
      comment: "显示顺序",
    },

    // 数据范围 - 对应MySQL的data_scope
    dataScope: {
      type: String,
      enum: {
        values: ["1", "2", "3", "4"],
        message:
          "数据范围必须是 1(全部数据权限)、2(自定数据权限)、3(本部门数据权限) 或 4(本部门及以下数据权限)",
      },
      default: "1",
      comment:
        "数据范围（1：全部数据权限 2：自定数据权限 3：本部门数据权限 4：本部门及以下数据权限）",
    },

    // 菜单树选择项是否关联显示 - 对应MySQL的menu_check_strictly
    menuCheckStrictly: {
      type: Boolean,
      default: true,
      comment: "菜单树选择项是否关联显示",
    },

    // 部门树选择项是否关联显示 - 对应MySQL的dept_check_strictly
    deptCheckStrictly: {
      type: Boolean,
      default: true,
      comment: "部门树选择项是否关联显示",
    },

    // 角色状态 - 对应MySQL的status
    status: {
      type: String,
      required: [true, "角色状态不能为空"],
      enum: {
        values: ["0", "1"],
        message: "角色状态必须是 0(正常) 或 1(停用)",
      },
      index: true,
      comment: "角色状态（0正常 1停用）",
    },

    // 删除标志 - 对应MySQL的del_flag
    delFlag: {
      type: String,
      enum: {
        values: ["0", "2"],
        message: "删除标志必须是 0(存在) 或 2(删除)",
      },
      default: "0",
      index: true,
      comment: "删除标志（0代表存在 2代表删除）",
    },

    // 创建者 - 对应MySQL的create_by
    createBy: {
      type: String,
      default: "",
      comment: "创建者",
    },

    // 创建时间 - 对应MySQL的create_time
    createTime: {
      type: Date,
      default: Date.now,
      comment: "创建时间",
    },

    // 更新者 - 对应MySQL的update_by
    updateBy: {
      type: String,
      default: "",
      comment: "更新者",
    },

    // 更新时间 - 对应MySQL的update_time
    updateTime: {
      type: Date,
      default: Date.now,
      comment: "更新时间",
    },

    // 备注 - 对应MySQL的remark
    remark: {
      type: String,
      default: null,
      maxlength: [500, "备注不能超过500个字符"],
      comment: "备注",
    },
  },
  {
    // Schema 选项
    timestamps: false,
    collection: "sys_roles",
    toJSON: { virtuals: true },
    toObject: { virtuals: true },
  }
);

// 创建复合索引
sysRoleSchema.index({ delFlag: 1, status: 1 });
sysRoleSchema.index({ roleKey: 1 }, { unique: true });
sysRoleSchema.index({ roleSort: 1 });
sysRoleSchema.index({ createTime: -1 });

// 虚拟字段
sysRoleSchema.virtual("isActive").get(function () {
  return this.status === "0" && this.delFlag === "0";
});

sysRoleSchema.virtual("statusText").get(function () {
  const statusMap = { 0: "正常", 1: "停用" };
  return statusMap[this.status] || "未知";
});

sysRoleSchema.virtual("dataScopeText").get(function () {
  const dataScopeMap = {
    1: "全部数据权限",
    2: "自定数据权限",
    3: "本部门数据权限",
    4: "本部门及以下数据权限",
  };
  return dataScopeMap[this.dataScope] || "未知";
});

// 实例方法
sysRoleSchema.methods = {
  // 启用/禁用角色
  toggleStatus: function () {
    this.status = this.status === "0" ? "1" : "0";
    this.updateTime = new Date();
    return this.save();
  },

  // 软删除角色
  softDelete: function () {
    this.delFlag = "2";
    this.updateTime = new Date();
    return this.save();
  },

  // 恢复角色
  restore: function () {
    this.delFlag = "0";
    this.updateTime = new Date();
    return this.save();
  },

  // 更新角色信息
  updateRole: function (updateData) {
    Object.keys(updateData).forEach((key) => {
      if (key !== "roleId" && this.schema.paths[key]) {
        this[key] = updateData[key];
      }
    });
    this.updateTime = new Date();
    return this.save();
  },

  // 获取角色基本信息（用于展示）
  toBasicJSON: function () {
    return {
      roleId: this.roleId,
      roleName: this.roleName,
      roleKey: this.roleKey,
      roleSort: this.roleSort,
      dataScope: this.dataScope,
      dataScopeText: this.dataScopeText,
      menuCheckStrictly: this.menuCheckStrictly,
      deptCheckStrictly: this.deptCheckStrictly,
      status: this.status,
      statusText: this.statusText,
      remark: this.remark,
    };
  },

  // 验证角色权限字符串格式
  validateRoleKey: function () {
    const roleKeyRegex = /^[A-Z_]+$/;
    return roleKeyRegex.test(this.roleKey);
  },

  // 检查是否有数据权限
  hasDataScope: function (scope) {
    return this.dataScope === scope;
  },

  // 检查是否是管理员角色（通常admin角色有特殊权限）
  isAdminRole: function () {
    return this.roleKey === "ADMIN";
  },
};

// 静态方法
sysRoleSchema.statics = {
  // 根据角色ID查找角色
  findByRoleId: function (roleId) {
    return this.findOne({
      roleId: roleId,
      delFlag: "0",
    });
  },

  // 根据角色权限字符串查找角色
  findByRoleKey: function (roleKey) {
    return this.findOne({
      roleKey: roleKey.toUpperCase(),
      delFlag: "0",
    });
  },

  // 根据角色名称查找角色
  findByRoleName: function (roleName) {
    return this.findOne({
      roleName: new RegExp(`^${roleName}$`, "i"),
      delFlag: "0",
    });
  },

  // 获取所有有效角色（按显示顺序排序）
  findActiveRoles: function () {
    return this.find({
      delFlag: "0",
      status: "0",
    }).sort({ roleSort: 1 });
  },

  // 获取所有角色（包含停用的）
  findAllRoles: function () {
    return this.find({ delFlag: "0" }).sort({ roleSort: 1, roleId: 1 });
  },

  // 分页查询角色
  findRolesPaginated: function (options = {}) {
    const {
      page = 1,
      limit = 10,
      roleName = "",
      roleKey = "",
      status = "",
      dataScope = "",
    } = options;

    const skip = (page - 1) * limit;
    const query = { delFlag: "0" };

    // 构建查询条件
    if (roleName) {
      query.roleName = { $regex: roleName, $options: "i" };
    }

    if (roleKey) {
      query.roleKey = { $regex: roleKey, $options: "i" };
    }

    if (status) {
      query.status = status;
    }

    if (dataScope) {
      query.dataScope = dataScope;
    }

    return Promise.all([
      this.find(query).skip(skip).limit(limit).sort({ roleSort: 1, roleId: 1 }),
      this.countDocuments(query),
    ]).then(([roles, total]) => ({
      roles,
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total,
        pages: Math.ceil(total / limit),
      },
    }));
  },

  // 角色统计
  getRoleStats: function () {
    return this.aggregate([
      {
        $match: { delFlag: "0" },
      },
      {
        $group: {
          _id: "$status",
          count: { $sum: 1 },
          avgRoleSort: { $avg: "$roleSort" },
        },
      },
      {
        $project: {
          status: "$_id",
          count: 1,
          avgRoleSort: { $round: ["$avgRoleSort", 2] },
          _id: 0,
        },
      },
      {
        $sort: { status: 1 },
      },
    ]);
  },

  // 数据范围统计
  getDataScopeStats: function () {
    return this.aggregate([
      {
        $match: {
          delFlag: "0",
          status: "0",
        },
      },
      {
        $group: {
          _id: "$dataScope",
          count: { $sum: 1 },
        },
      },
      {
        $project: {
          dataScope: "$_id",
          count: 1,
          _id: 0,
        },
      },
      {
        $sort: { dataScope: 1 },
      },
    ]);
  },

  // 检查角色权限字符串是否已存在
  isRoleKeyExists: function (roleKey, excludeRoleId = null) {
    const query = {
      roleKey: roleKey.toUpperCase(),
      delFlag: "0",
    };

    if (excludeRoleId) {
      query.roleId = { $ne: excludeRoleId };
    }

    return this.findOne(query);
  },

  // 检查角色名称是否已存在
  isRoleNameExists: function (roleName, excludeRoleId = null) {
    const query = {
      roleName: new RegExp(`^${roleName}$`, "i"),
      delFlag: "0",
    };

    if (excludeRoleId) {
      query.roleId = { $ne: excludeRoleId };
    }

    return this.findOne(query);
  },

  // 批量更新角色状态
  batchUpdateStatus: function (roleIds, status, updateBy = "") {
    return this.updateMany(
      { roleId: { $in: roleIds } },
      {
        status: status,
        updateBy: updateBy,
        updateTime: new Date(),
      }
    );
  },

  // 获取最大显示顺序
  getMaxRoleSort: function () {
    return this.findOne({ delFlag: "0" })
      .sort({ roleSort: -1 })
      .select("roleSort")
      .then((role) => (role ? role.roleSort : 0));
  },

  // 获取下一个可用的角色ID
  getNextRoleId: async function () {
    const lastRole = await this.findOne({ delFlag: "0" })
      .sort({ roleId: -1 })
      .select("roleId");

    return lastRole ? lastRole.roleId + 1 : 100; // 从100开始
  },

  // 根据角色ID列表获取角色信息
  findRolesByIds: function (roleIds) {
    return this.find({
      roleId: { $in: roleIds },
      delFlag: "0",
    }).sort({ roleSort: 1 });
  },

  // 搜索角色（名称或权限字符串）
  searchRoles: function (keyword, options = {}) {
    const { page = 1, limit = 10, status = "", dataScope = "" } = options;

    const skip = (page - 1) * limit;
    const query = {
      delFlag: "0",
      $or: [
        { roleName: { $regex: keyword, $options: "i" } },
        { roleKey: { $regex: keyword, $options: "i" } },
      ],
    };

    // 状态筛选
    if (status) {
      query.status = status;
    }

    // 数据范围筛选
    if (dataScope) {
      query.dataScope = dataScope;
    }

    return Promise.all([
      this.find(query).skip(skip).limit(limit).sort({ roleSort: 1, roleId: 1 }),
      this.countDocuments(query),
    ]).then(([roles, total]) => ({
      roles,
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total,
        pages: Math.ceil(total / limit),
      },
    }));
  },

  // 获取管理员角色（通常用于系统初始化）
  getAdminRole: function () {
    return this.findOne({
      roleKey: "ADMIN",
      delFlag: "0",
    });
  },

  // 根据数据范围获取角色
  findRolesByDataScope: function (dataScope) {
    return this.find({
      dataScope: dataScope,
      delFlag: "0",
      status: "0",
    }).sort({ roleSort: 1 });
  },
};

// 查询助手
sysRoleSchema.query = {
  // 按状态筛选
  byStatus: function (status) {
    return this.where("status").equals(status);
  },

  // 按删除状态筛选
  byDelFlag: function (delFlag = "0") {
    return this.where("delFlag").equals(delFlag);
  },

  // 按数据范围筛选
  byDataScope: function (dataScope) {
    return this.where("dataScope").equals(dataScope);
  },

  // 按显示顺序排序
  sortByOrder: function (direction = "asc") {
    const sortOrder = direction === "desc" ? -1 : 1;
    return this.sort({ roleSort: sortOrder });
  },

  // 搜索角色名称或权限字符串
  searchByKeyword: function (keyword) {
    return this.where({
      $or: [
        { roleName: { $regex: keyword, $options: "i" } },
        { roleKey: { $regex: keyword, $options: "i" } },
      ],
    });
  },

  // 只查询有效的角色（未删除且启用）
  onlyActive: function () {
    return this.where({
      delFlag: "0",
      status: "0",
    });
  },
};

// 中间件
sysRoleSchema.pre("save", function (next) {
  // 更新更新时间
  this.updateTime = new Date();

  // 角色权限字符串转大写
  if (this.isModified("roleKey")) {
    this.roleKey = this.roleKey.toUpperCase();
  }

  // 验证角色权限字符串格式
  if (this.isModified("roleKey") && !this.validateRoleKey()) {
    return next(
      new Error("角色权限字符串格式不正确，只能包含大写字母和下划线")
    );
  }

  next();
});

// 创建模型
const SysRole = mongoose.model("SysRole", sysRoleSchema);

module.exports = SysRole;
